package at.fhooe.engine.graphics;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import at.fhooe.engine.event.events.WindowCloseRequestEvent;
import at.fhooe.engine.pandora.Game;
//TODO see eleraning Do not access subsystems from within other subsystems by the use of globals or singletons!

public class GraphicsSystem implements WindowCloseRequestEvent.Listener {

	private RenderSystem m_renderSystem;
	private Graphics2D m_graphics;
	private double m_timeForOneFrame = 0.0;
	private int m_width;
	private int m_height;
	private double m_scaleX;
	private double m_scaleY;
	
	public GraphicsSystem() {
		m_renderSystem = new RenderSystem();
		m_scaleX = 1.0;
		m_scaleY = 1.0;
	}
	
	public void setFPS(int fps) {
		if(fps <= 0) {
			m_timeForOneFrame = 0;
		} else {
			m_timeForOneFrame = 1.0 / (double) fps;
		}
	}
	
	public void open(int width, int height, boolean fullscreen) {
		m_renderSystem.open(width, height, fullscreen);
		m_width = width;
		m_height = height;
	}
	
	public void close() {
		m_renderSystem.close();
	}
	
	public void addKeyListener(KeyListener keyListener) {
		m_renderSystem.addKeyListener(keyListener);
	}
	
	public void addMouseListener(MouseListener mouseListener) {
		m_renderSystem.addMouseListener(mouseListener);
	}
	
	public void addMouseMotionListener(MouseMotionListener mouseMotionListener) {
		m_renderSystem.addMouseMotionListener(mouseMotionListener);
	}
	
	//TODO synchronized??
	public void update() {
		m_graphics = m_renderSystem.beginUpdate();
		m_graphics.clearRect(0, 0, m_width, m_height);
		m_graphics.scale(m_scaleX, m_scaleX);
		
		Game.getInstance().getSceneNodeManager().drawNodes(m_graphics);
		displayFPS(m_graphics);
		
		m_graphics.dispose();
		m_renderSystem.endUpdate();
		
		frameRateGoverning();
	}
	
	private void displayFPS(Graphics2D m_graphics) {
		int fps = Game.getInstance().getFPS();
		if(fps < 0) {
			return;
		}
		m_graphics.setFont( new Font( "Courier New", Font.PLAIN, 16 ) );
		m_graphics.setColor( Color.BLACK );
		m_graphics.drawString( String.format( "FPS: %s", fps ), 20, 20 );
	}

	private void  frameRateGoverning() {
		double deltaTime = Game.getInstance().getTimeSinceLastTick();
		if(deltaTime < m_timeForOneFrame) {
			try {
				Thread.sleep((long) ((m_timeForOneFrame - deltaTime) * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void setScaleY(double scaleY) {
		setScale(m_scaleX, scaleY);
	}
	
	public void setScaleX(double scaleX) {
		setScale(scaleX, m_scaleY);
	}
	
	public void setScale(double scaleX, double scaleY) {
		m_scaleX = scaleX;
		m_scaleY = scaleY;
	}
	
	public double getScaleX() {
		return m_scaleX;
	}
	
	public double getScaleY() {
		return m_scaleY;
	}

	public void onWindowCloseRequest(WindowCloseRequestEvent windowCloseRequestEvent) {
		this.close();
	}
	
	//TODO this is normally in the current state but I'm not sure!
	public int getWidth() {
		return m_width;
	}
	
	public int getHeight() {
		return m_height;
	}
}
